package types

import (
	"bufio"
	"encoding/binary"
	"net"
)

type VncConn struct {
	C         net.Conn
	Br        *bufio.Reader
	Bw        *bufio.Writer
	Listeners []*MessageListener
	ErrCh     chan error
	QuitCh    chan error
}

// Handler represents handler of handshake
type Handler interface {
	Handle(c *VncConn) error
}
type MessageListener interface {
	Handle(c *VncConn)
}

// Conn return underlining net.Conn
func (c *VncConn) Conn() net.Conn {
	return c.C
}

// Close closing conn
func (c *VncConn) Close() error {
	return c.C.Close()
}

func (c *VncConn) Read(data interface{}) error {
	return binary.Read(c.C, binary.BigEndian, data)
}

func (c *VncConn) Write(data interface{}) error {
	return binary.Write(c.C, binary.BigEndian, data)
}

// BufRead bufio Read data from conn
func (c *VncConn) BufRead(buf []byte) (int, error) {
	return c.Br.Read(buf)
}

// BufWrite bufio Write data to conn must be Flushed
func (c *VncConn) BufWrite(buf []byte) (int, error) {
	return c.Bw.Write(buf)
}

// BufFlush bufio Flush flushes data to conn
func (c *VncConn) BufFlush() error {
	return c.Bw.Flush()
}

func (c *VncConn) GetListeners() []*MessageListener {
	return c.Listeners
}
func (c *VncConn) AddListeners(listener *MessageListener) {
	c.Listeners = append(c.Listeners, listener)
}
func (c *VncConn) SetListeners(listeners []*MessageListener) {
	c.Listeners = listeners
}

func (c *VncConn) RunListeners() {
	for _, listener := range c.Listeners {
		go (*listener).Handle(c)
	}
}
func (c *VncConn) ListenChan() (err error) {
	for {
		select {
		case err = <-c.ErrCh:
			//logger.LogErr("vncConn error:", err)
			c.Close()
			return
			break
		case err = <-c.QuitCh:
			//logger.LogErr("vncConn quit:", err)
			c.Close()
			return
			break
		default:
			break
		}
	}
}

func (c *VncConn) ReadErrorReason() string {
	var reasonLen uint32
	if err := c.Read(&reasonLen); err != nil {
		return "<error>"
	}

	reason := make([]uint8, reasonLen)
	if err := c.Read(&reason); err != nil {
		return "<error>"
	}

	return string(reason)
}
